package com.amizah.tooling.utils.console;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


/**
 *@author Zaheer Abzal
 *@version 1.0.0 
 *<p><b>Description:</b> Provides a simplified means of writing and reading data to and from the console.</p> 
 *<p><b>External Dependents:</b> none
 *<p><b>Date Created:</b> 3/13/2011 </p>
 *<p><b>Last Updated:</b>  </p>
 */

public class Console implements IConsole {

	private boolean suppressErrorReporting = false;
	private boolean errorFlag = false;
	private String errorMessage;
	
	/**
	 * <p><b>Description:</b> Creates an instance of the Console object.</p> 
	 */
	public Console()
	{
		super();
	}
	
	/**
	 * @param data - Data of a String data type to write to standard out (i.e the console).
	 */	
	public void write(String data) {
		
		System.out.print(data);

	}

	/**
	 * @param data - Data of a double data type to write to standard out (i.e the console).
	 */
	public void write(double data) {
		
		System.out.print(data);

	}

	/**
	 * @param data - Data of a float data type to write to standard out (i.e the console).
	 */
	public void write(float data) {
		
		System.out.print(data);

	}

	/**
	 * @param data - Data of an int data type to write to standard out (i.e the console).
	 */
	public void write(int data) {
		
		System.out.print(data);
	}
	
	/**
	 * @param data - Data of a boolean ('true' or 'false') data type to write to standard out (i.e the console).
	 */
	public void write(boolean data) {
		
		System.out.print(data);
	}
	
	/**
	 * @return data formatted as String data type.
	 * @throws IOException
	 */
	public String readString()throws IOException {
		
		String data = "";
			
		BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
		
		data = bufferRead.readLine();
		
		return data;
	}
	

	/**
	 * @return data formatted as int data type.
	 * @throws IOException
	 */
	public int readInt()throws IOException 
	{
	
		Integer asInt = 0;
		String data = null;
		
		this.setErrorFlag(false);
		this.setErrorMessage("");
		
		BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
		data = bufferRead.readLine();
			
	 
			try {
				asInt = Integer.parseInt(data);
			} catch (NumberFormatException e) {
				
				this.setErrorMessage("Value is not of type Integer (int).");
									
				if(!this.suppressErrorReporting)
					this.write(this.getErrorMessage());
				
				this.setErrorFlag(true);
				
			}
			
		return asInt;
		
	}

	/**
	 * @return data formatted as double data type.
	 * @throws IOException
	 */
	public double readDouble()throws IOException 
	{
	
		double asDouble = 0;
		String data = null;	
		
		this.setErrorFlag(false);
		this.setErrorMessage("");
		
		
		BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
		data = bufferRead.readLine();
		
		try{
			asDouble = Double.parseDouble(data);
	    } catch (NumberFormatException e) {
		
		this.setErrorMessage("Value is not of type double.");
							
		if(!this.suppressErrorReporting)
			this.write(this.getErrorMessage());
		
		this.setErrorFlag(true);
		
	    }
		
		return asDouble;
	}
	
	/**
	 * @return data formatted as float data type.
	 * @throws IOException
	 */
	public float readFloat()throws IOException 
	{
		
		float asFloat = 0;
		String data = null;
		
		this.setErrorFlag(false);
		this.setErrorMessage("");
		
	    BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
	    data = bufferRead.readLine();
		
	    try{ 
			asFloat = Float.parseFloat(data);
		} catch (NumberFormatException e) {
		
			this.setErrorMessage("Value is not of type float.");
							
			if(!this.suppressErrorReporting)
				this.write(this.getErrorMessage());
		
			this.setErrorFlag(true);
		
	    }
				
	    return asFloat;
		
	}
	
	/**
	 * @return data formatted as boolean data type.
	 * @throws IOException
	 */
	public boolean readBoolean() throws IOException 
	{
		
		boolean asBool = false;
		String s = null;
	
		this.setErrorFlag(false);
		this.setErrorMessage("");
		
		BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
		s = bufferRead.readLine();
					
		asBool = Boolean.parseBoolean(s);  	   
		
		 if(!Boolean.valueOf(asBool))
		 {
			 this.setErrorMessage("The value entered was not a boolean. Enter only 'true' or 'false'.");
		     
				 if(!this.suppressErrorReporting)
						this.write(this.getErrorMessage());
				
					this.setErrorFlag(true);	 
				 			    	
		 }
			 		
			return asBool;
			 
	}


	/**
	 * <p><b>Description:</b> Creates a new line in the console.</p> 
	 */
	public void newLine() {
		
		System.out.print("\n");
	}
	
	/**
	 * @param flag - Can be 'true' or 'false'.
	 * <p><b>Description:</b>Used  to set the automatic error reporting on or off respectively. If error reporting is suppressed,
	 * the user is responsible for handling the error.</p> 
	 */
	public void suppressErrors(boolean flag)
	{
		suppressErrorReporting = flag;
	}
	
	/**
	 * @return Current error suppress state, i.e. either 'true' or 'false'.
	 */
	public boolean suppressErrorsState()
	{
		return suppressErrorReporting;
	}
	
	/**
	 * @return Current state of error flag.
	 * <p><b>Description:</b>Used with numeric and boolean read methods to catch and report on 'NumberFormatException'. If there is an exception
	 * the flag is set to 'true'. The user can test the flag to determine how to handle output.</p> 
	 */
	public boolean getErrorFlag()
	{
		return errorFlag;
	}
	
	/**
	 * @return Error message as a String set the numeric and boolean read methods.
	 * <p><b>Description:</b>Used with numeric and boolean read methods to catch are report on 'NumberFormatException'. If there is an exception
	 * a String message is set stating what happened. If error reporting is not suppressed the message is written to the console automatically.</p>
	 */
	public String getErrorMessage()
	{
		return errorMessage;
	}
	
	/**
	 * @param msg - Message as a String to set.
	 * <p><b>Description:</b>Used with numeric and boolean read methods to set error messages.</p>
	 */
	private void setErrorMessage(String msg)
	{
		errorMessage = msg;
	}
	
	/**
	 * @param flag - Can be 'true' or 'false'.
	 * <p><b>Description:</b>Used with numeric and boolean read methods to set error flag.</p>
	 */
	private void setErrorFlag(boolean flag)
	{
		errorFlag = flag;
	}
	
}
